﻿#region [     文件信息     ]

/*----------------------------------------------------------------
 * CLR版本：4.0.30319.42000
 * 机器名称：VAMPIREWAL
 * 公司名称：Organization
 * 命名空间：Vampirewal.Core.Tools
 * 唯一标识：71043946-7832-4e7f-aa65-af9537c2ba14
 * 文件名：Enumeration
 * 当前用户域：VAMPIREWAL
 *
 * 创建者：Administrator
 * 电子邮箱：235160615@qq.com
 * 创建时间：2023/6/13 10:31:49
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion [     文件信息     ]

namespace Vampirewal.Core;

/// <summary>
/// 智能枚举
/// </summary>
public abstract class Enumeration<TEnum> : IEquatable<Enumeration<TEnum>> where TEnum : Enumeration<TEnum>
{
    private static readonly Dictionary<int, TEnum> Enumerations = GetEnumerations();

    /// <summary>
    /// 枚举类型
    /// </summary>
    private static readonly Type EnumType = typeof(TEnum);

    /// <summary>
    /// 名称
    /// </summary>
    public string Name { get; protected init; }

    /// <summary>
    /// 值
    /// </summary>
    public int Value { get; protected init; }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="value"></param>
    /// <param name="name"></param>
    protected Enumeration(int value, string name)
    {
        Value = value;
        Name = name;
    }

    /// <summary>
    /// 通过名称获取
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public static TEnum FromName(string name) => Enumerations.Values.SingleOrDefault(x => x.Name == name);

    /// <summary>
    /// 通过值获取
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static TEnum FromValue(int value) => Enumerations.TryGetValue(value, out var enumeration) ? enumeration : default;

    /// <summary>
    /// 是否包含
    /// </summary>
    /// <param name="other"></param>
    /// <returns></returns>
    public bool Equals(Enumeration<TEnum> other) => other is not null && GetType() == other.GetType() && Value == other.Value;

    /// <summary>
    /// 是否包含
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public override bool Equals(object obj) => obj is Enumeration<TEnum> other && Equals(other);
    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public override int GetHashCode() => HashCode.Combine(Value, Name);

    private static Dictionary<int, TEnum> GetEnumerations() => EnumType
        .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
        .Where(x => EnumType.IsAssignableFrom(x.FieldType))
        .Select(x => (TEnum)x.GetValue(default)).ToDictionary(x => x?.Value ?? 0);
}